home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 October: Mac OS SDK / Dev.CD Oct 97 SDK1.toast / Development Kits (Disc 1) / AsyncDriverSample1.0b4 / DropMounter / DropMounter.p < prev    next >
Encoding:
Text File  |  1997-05-21  |  11.0 KB  |  354 lines  |  [TEXT/CWIE]

  1. program DropMounter;
  2.  
  3. (*
  4.     File:        DropMounter.p
  5.  
  6.     Contains:    A tiny utility to mount disk images using the AsyncDriverSample.
  7.  
  8.     Written by:    Quinn "The Eskimo!"
  9.  
  10.     Copyright:    © 1996 by Apple Computer, Inc., all rights reserved.
  11.  
  12.     Change History (most recent first):
  13.  
  14.     You may incorporate this sample code into your applications without
  15.     restriction, though the sample code has been provided "AS IS" and the
  16.     responsibility for its operation is 100% yours.  However, what you are
  17.     not permitted to do is to redistribute the source as "DSC Sample Code"
  18.     after having made changes. If you're going to re-distribute the source,
  19.     we require that you make it clear in the source that the code was
  20.     descended from Apple Sample Code, but that you've made changes.
  21. *)
  22.  
  23. (* This application is a trivial DropShell type program that first installs
  24.     the disk image mounting driver (in this case it's ".AsyncDriverSample"
  25.     although the name of the driver is in a resource, so the application
  26.     can be retargetted).
  27.    After that it spins in a main event loop, handling AppleEvents as they
  28.     come in.  In response to a Open Document AppleEvent, the program calls
  29.     the driver to process the file.  The ".AsyncDriverSample" sample responds
  30.     to this by mounting the disk image.
  31. *)
  32.  
  33.     uses
  34.         Types,
  35.         Files,
  36.         EPPC,
  37.         AppleEvents,
  38.         Memory,
  39.         Errors,
  40.         Events,
  41.         QuickDraw,
  42.         Fonts,
  43.         Windows,
  44.         Menus,
  45.         TextEdit,
  46.         Dialogs,
  47.         TextUtils,
  48.         Devices,
  49.         Resources,
  50.         
  51.         TradDriverLoaderLib,
  52.         
  53.         AsyncDriverCommon;
  54.  
  55.     (* ***** Application Resource Equates ***** *)
  56.     
  57.     const
  58.         (* STR *)
  59.         rDriverNameString = 128;            (* The name of the 'DRVR' we are to install. *)
  60.         rPhysicalDescriptionString = 200;    (* The physical description string to pass to the driver. *)
  61.         rMediaDescriptionString = 200;        (* The media description string to pass to the driver. *)
  62.         (* ICN# *)
  63.         rPhysicalIcon = 200;                (* The physical icon to pass to the driver. *)
  64.         rMediaIcon = 201;                    (* The media icon to pass to the driver. *)
  65.         (* vers *)
  66.         rDriverVersion = 200;                (* The version of the device driver. *)
  67.         (* ALRT *)
  68.         rErrorAlert = 128;
  69.         rAboutAlert = 129;
  70.             
  71.  
  72.     (* ***** Global Variables ***** *)
  73.         
  74.     var
  75.         gQuitNow: Boolean;                    (* Set to true when you want the main event loop to stop. *)
  76.         gDriverRefNum : DriverRefNum;        (* The refnum of the disk image mounting driver. *)
  77.  
  78.     (* ***** Silly Little Utilities ***** *)
  79.  
  80.     procedure DisplayError(errNum : OSStatus);
  81.         (* A trivial error dialog. *)
  82.         var
  83.             junk : integer;
  84.             errStr : Str255;
  85.     begin
  86.         if (errNum <> noErr) & (errNum <> userCanceledErr) then begin
  87.             NumToString(errNum, errStr);
  88.             ParamText(errStr, '', '', '');
  89.             junk := StopAlert(rErrorAlert, nil);
  90.         end; (* if *)
  91.     end; (* DisplayError *)
  92.     
  93.     procedure BlockClear(baseAddr: univ Ptr; size: longint);
  94.         (* Why oh why doesn't the OS provide this!?! *)
  95.     begin
  96.         while (size > 0) do begin
  97.             baseAddr^ := 0;
  98.             inc(longint(baseAddr));
  99.             size := size - 1;
  100.         end; (* while *)
  101.     end; (* BlockClear *)
  102.     
  103.     (* ***** Core Functions ***** *)
  104.  
  105.     function DoOpenApplication : OSStatus;
  106.         (* In response to the Open Application AppleEvent, we display the about box. *)
  107.         var
  108.             junk : integer;
  109.     begin
  110.         junk := Alert(rAboutAlert, nil);
  111.         gQuitNow := true;
  112.         DoOpenApplication := noErr;
  113.     end; (* DoOpenApplication *)
  114.  
  115.     function DoOpenDocument(fss : FSSpec) : OSStatus;
  116.         (* In response to the Open Document AppleEvent, call the disk image driver
  117.             to mount the disk image.
  118.                 
  119.            Note that use of PBControlImmed.  This is critical to the successful operation
  120.             of the driver.  The driver must have non-interrupt time to mount the image.
  121.             If you call PBControlSync, the call could be delayed by a
  122.             pending async call.  The sync call would then start at
  123.             interrupt time, and the device driver would fail horrible.
  124.             
  125.            See Technote 1067 for an extended description of this issue.
  126.                 
  127.             <http://devworld.apple.com/dev/technotes/tn/tn1067.html>
  128.         *)
  129.         var
  130.             err: OSStatus;
  131.             mpb : MountParamBlock;
  132.     begin
  133.         mpb.ioCRefNum := gDriverRefNum;
  134.         mpb.csCode := kMountImageControlCode;
  135.         mpb.csParamFileToMount := @fss;
  136.         err := PBControlImmed(@mpb);
  137.         gQuitNow := true;
  138.         DoOpenDocument := err;
  139.     end; (* DoOpenDocument *)
  140.     
  141.     function InstallAndOpenDriver : OSErr;
  142.         var
  143.             err : OSErr;
  144.             driverName : Str255;
  145.             initParamBlock : SecondaryInitParamBlock;
  146.             mediaIcon : IconType;
  147.             physicalIcon : IconType;
  148.             physicalLocationString : Str255;
  149.             tmpResourceH : Handle;
  150.     begin
  151.         (* Get the name for the driver and install it. *)
  152.         driverName := GetString(rDriverNameString)^^;
  153.         err := TradInstallDriverFromResource(0, @driverName,
  154.                                                 48,
  155.                                                 TradHighestUnitNumber + 1,
  156.                                                 gDriverRefNum);
  157.         if (err = noErr) or (err = dupFNErr) then begin
  158.             err := TradOpenInstalledDriver(gDriverRefNum, fsRdWrPerm);
  159.         end; (* if *)
  160.  
  161.         (* Now send it the secondary init control call, passing in all sorts of nice resource info. *)
  162.         if err = noErr then begin
  163.  
  164.             (* First clear out the paramblock, so if any of the resources fail to load
  165.                     we have defined results.
  166.             *)
  167.             BlockClear(@initParamBlock, sizeof(initParamBlock));
  168.             
  169.             (* Get and copy in the driver version. *)
  170.             tmpResourceH := Get1Resource('vers', rDriverVersion);
  171.             if tmpResourceH <> nil then begin
  172.                 initParamBlock.csParamVersion := VersRecHndl(tmpResourceH)^^.numericVersion;
  173.             end; (* if *)
  174.             
  175.             (* Get and copy in the media icon. *)
  176.             tmpResourceH := Get1Resource('ICN#', rMediaIcon);
  177.             if tmpResourceH <> nil then begin
  178.                 BlockMove(tmpResourceH^, @initParamBlock.csParamMediaIcon, sizeof(IconType));
  179.             end; (* if *)
  180.             
  181.             (* Get and copy in the location string. *)
  182.             tmpResourceH := Get1Resource('STR ', rMediaDescriptionString);
  183.             if tmpResourceH <> nil then begin
  184.                 initParamBlock.csParamMediaDescription := StringHandle(tmpResourceH)^^;
  185.             end; (* if *)
  186.  
  187.             (* Get and copy in the physical icon. *)
  188.             tmpResourceH := Get1Resource('ICN#', rPhysicalIcon);
  189.             if tmpResourceH <> nil then begin
  190.                 BlockMove(tmpResourceH^, @initParamBlock.csParamPhysicalIcon, sizeof(IconType));
  191.             end; (* if *)
  192.             
  193.             (* Get and copy in the location string. *)
  194.             tmpResourceH := Get1Resource('STR ', rPhysicalDescriptionString);
  195.             if tmpResourceH <> nil then begin
  196.                 initParamBlock.csParamPhysicalDescription := StringHandle(tmpResourceH)^^;
  197.             end; (* if *)
  198.             
  199.             (* Now fill in the rest of the initParamBlock and send it to the driver. *)
  200.             initParamBlock.ioCRefNum := gDriverRefNum;
  201.             initParamBlock.csCode := kSecondaryInitControlCode;
  202.             err := PBControlImmed(@initParamBlock);
  203.         end; (* if *)
  204.  
  205.         InstallAndOpenDriver := err;
  206.     end; (* InstallAndOpenDriver *)
  207.     
  208.     (* ***** Standard AppleEvent Handling Stuff ***** *)
  209.     
  210.     function AEGotRequiredParams (theAppleEvent: AppleEvent): OSStatus;
  211.         (* Copied out of "Inside Macintosh: Inter-Application Communications". *)
  212.         var
  213.             typeCode: DescType;
  214.             actualSize: Size;
  215.             err: OSStatus;
  216.     begin
  217.         err := AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard, typeCode, nil, 0, actualSize);
  218.         if err = errAEDescNotFound then begin
  219.             err := noErr;
  220.         end else if err = noErr then begin
  221.             err := errAEEventNotHandled;
  222.         end; (* if *)
  223.         AEGotRequiredParams := err;
  224.     end; (* AEGotRequiredParams *)
  225.  
  226.     function HandleAEOpenApplication (var theAppleEvent : AppleEvent; var reply: AppleEvent; refcon : longint): OSErr;
  227.         (* Handle the Open Application AppleEvent. Basically this does the standard AppleEvent
  228.             stuff, then passes the event off to the DoOpenApplication routine.
  229.         *)
  230.         var
  231.             err: OSStatus;
  232.     begin
  233.         {$unused reply}
  234.         {$unused refcon}
  235.         err := AEGotRequiredParams(theAppleEvent);
  236.         if err = noErr then begin
  237.             err := DoOpenApplication;
  238.             if err <> noErr then begin
  239.                 if AEInteractWithUser(kAEDefaultTimeout, nil, nil) = noErr then begin
  240.                     DisplayError(err);
  241.                 end; (* if *)
  242.             end; (* if *)
  243.         end; (* if *)
  244.         HandleAEOpenApplication := err;
  245.     end; (* HandleAEOpenApplication *)
  246.  
  247.     function HandleAEOpenDocuments (var theAppleEvent : AppleEvent; var reply: AppleEvent; refcon : longint): OSErr;
  248.         (* Handle the Open Documents AppleEvent. Basically this does the standard AppleEvent
  249.             stuff, then passes the event off to the DoOpenDocument routine.
  250.         *)
  251.         var
  252.             err : OSStatus;
  253.             docList: AEDescList;
  254.             numberOfItemsInList: longint;
  255.             index : longint;
  256.             docToOpen: FSSpec;
  257.             junkKeyword: AEKeyword;
  258.             junkActualSize: Size;
  259.             junkTypeCode: DescType;
  260.             junkErr : OSStatus;
  261.     begin
  262.         {$unused reply}
  263.         {$unused refcon}
  264.         err := AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, docList);
  265.         if err = noErr then begin
  266.             err := AEGotRequiredParams(theAppleEvent);
  267.             if err = noErr then begin
  268.                 err := AECountItems(docList, numberOfItemsInList);
  269.             end; (* if *)
  270.             if err = noErr then begin
  271.                 for index := 1 to numberOfItemsInList do begin
  272.                     if AEGetNthPtr(docList, index, typeFSS, junkKeyword, junkTypeCode, @docToOpen, sizeof(docToOpen), junkActualSize) = noErr then begin
  273.                         err := DoOpenDocument(docToOpen);
  274.                         if err <> noErr then begin
  275.                             if AEInteractWithUser(kAEDefaultTimeout, nil, nil) = noErr then begin
  276.                                 DisplayError(err);
  277.                             end; (* if *)
  278.                         end; (* if *)
  279.                     end; (* if *)
  280.                 end; (* for *)
  281.                 err := noErr;
  282.             end; (* if *)
  283.             junkErr := AEDisposeDesc(docList);
  284.         end; (* if *)
  285.         HandleAEOpenDocuments := err;
  286.     end; (* HandleAEOpenDocuments *)
  287.  
  288.     function HandleAEQuitApplication (var theAppleEvent, reply: AppleEvent; refcon : longint): OSErr;
  289.         (* Handle the Quit AppleEvent. Basically this does the standard AppleEvent stuff, then 
  290.             sets gQuitNow and the application falls out of the main event loop.
  291.         *)
  292.         var
  293.             err: OSStatus;
  294.     begin
  295.         {$unused reply}
  296.         {$unused refcon}
  297.         err := AEGotRequiredParams(theAppleEvent);
  298.         if err = noErr then begin
  299.             gQuitNow := true;
  300.         end; (* if *)
  301.         HandleAEQuitApplication := err;
  302.     end; (* HandleAEQuitApplication *)
  303.  
  304.     (* ***** The Main Line! ***** *)
  305.  
  306.     var
  307.         err: OSErr;
  308.         junk: OSErr;
  309.         junkBool: boolean;
  310.         event: EventRecord;
  311. begin
  312.     (* Standard toolbox initialisation, courtesy of ObiWan. *)
  313.     InitGraf(@qd.thePort);
  314.     InitFonts;
  315.     InitWindows;
  316.     InitMenus;
  317.     TEInit;
  318.     InitDialogs(nil);
  319.     MaxApplZone;
  320.     MoreMasters;
  321.  
  322.     (* Install our AppleEvent handlers. Better hope we have System 7 (-: *)
  323.     junk := AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
  324.                             NewAEEventHandlerProc(@HandleAEOpenApplication), 0, false);
  325.     junk := AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, 
  326.                             NewAEEventHandlerProc(@HandleAEOpenDocuments), 0, false);
  327.     junk := AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, 
  328.                             NewAEEventHandlerProc(@HandleAEQuitApplication), 0, false);
  329.  
  330.     (* Now install the driver. *)
  331.     err := InstallAndOpenDriver;
  332.     
  333.     (* If everything is cool, do the main event loop. *)    
  334.     if err = noErr then begin
  335.         gQuitNow := false;
  336.         while not gQuitNow do begin
  337.             junkBool := WaitNextEvent(everyEvent, event, maxlongint, nil);
  338.             case event.what of
  339.                 keyDown: 
  340.                     gQuitNow := true;
  341.                 kHighLevelEvent: 
  342.                     junk := AEProcessAppleEvent(event);
  343.                 otherwise
  344.                     ;
  345.             end; (* case *)
  346.         end; (* while *)
  347.     end; (* if *)
  348.  
  349.     (* Display any errors starting up. *)
  350.     if err <> noErr then begin
  351.         DisplayError(err);
  352.     end; (* if *)
  353. end. (* MungeInstaller *)
  354.